﻿/**
Library: Alternative Transitioning
Author: Valentyn Derkach 2007.07.04
———————————————————————————————————————————————————————————————————————————————————————————————————————————————————
TweenProcessorInertialSpeeding performs tween processoring using inertial and speeding parameters.
The curSpeed is actually a change factor that is used for calculating the new value. curSpeed tends
to the dstSpeed and speedFactor is a change factor of this tending. Inertia is calculated as a 
multiplication of value offset and inertia factor. inertiaFade is a inertia fading factor.
In math idea is:
	changeFactor = (endChangeFactor - changeFactor)*speedFactor;
	offset = (endValue - currentValue)*changeFactor + inertia;
	inertia = offset*inertiaFactor + inertia*inertiaFadeFactor;
/**/

package com.bizmlib.transitioning
{

	import com.bizmlib.transitioning.ITweenProcessor;


	public class TweenProcessorInertialSpeeding extends Object implements ITweenProcessor
	{

		public var curSpeed:Number = 0;
		public var initSpeed:Number = 0;
		public var dstSpeed:Number = 0;
		public var speedFactor:Number = 0;
		public var minLimit:Number = 1;
		public var maxLimit:Number = Number.POSITIVE_INFINITY;
		public var inertiaFactor:Number = 0;
		public var inertiaFade:Number = 0;
		private var inertiaValues:Object;
		private var maxDValue:Number = 0;

		public function TweenProcessorInertialSpeeding(initSpeed:Number, endSpeed:Number, speedChangeFactor:Number,
		minLimit:Number, maxLimit:Number, inertiaFactor:Number, inertiaFade:Number){
			//trace(this + ".constructor(" + arguments + ")");
			inertiaValues = new Object();
			if(!isNaN(initSpeed)){this.initSpeed = curSpeed = initSpeed;}
			if(!isNaN(endSpeed)){dstSpeed = endSpeed;}
			if(!isNaN(speedChangeFactor)){speedFactor = speedChangeFactor;}
			if(!isNaN(minLimit)){this.minLimit = minLimit;}
			if(!isNaN(maxLimit)){this.maxLimit = maxLimit;}
			if(!isNaN(inertiaFactor)){this.inertiaFactor=inertiaFactor;}
			if(!isNaN(inertiaFade)){this.inertiaFade=inertiaFade;}
		}

		public function reInit():void{curSpeed = initSpeed;}

		public function onBeforeIteration():void{
			maxDValue = 0;
			curSpeed += (dstSpeed - curSpeed)*speedFactor;
		}

		public function performCalculation(propertyName:String, currentValue:Number, endValue:Number):Number{
			//trace("performCalculation(" + arguments + ")");
			var newValue:Number = currentValue, d:Number = 0;
			if(inertiaValues[propertyName]==undefined){inertiaValues[propertyName]=0;}
			if(Math.abs(currentValue-endValue)<minLimit && Math.abs(inertiaValues[propertyName])<minLimit){
				newValue = endValue;
				inertiaValues[propertyName] = 0;
			}else{
				d = (endValue - currentValue)*curSpeed + inertiaValues[propertyName];
				newValue = currentValue + d;
				inertiaValues[propertyName] = inertiaValues[propertyName]*inertiaFade + d*inertiaFactor;
			}
			maxDValue = Math.max(maxDValue, Math.abs(d));
			return newValue;
		}

		public function isFinal():Boolean{
			if(maxDValue == 0){return true;}
			return false;
		}

		public function onAfterIteration():void{
		}


		public function toString():String{return "[TweenProcessorInertialSpeeding]";}
	}
}